package com.pointcircle.estate.server.admin.web.rest;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.pointcircle.core.FrameworkConstant;
import com.pointcircle.core.entity.User;
import com.pointcircle.core.repository.UserRepository;
import com.pointcircle.core.service.PropertyService;
import com.pointcircle.core.util.JwtUtils;
import com.pointcircle.core.util.RestResponseUtils;
import com.pointcircle.core.web.RestResponse;
import com.pointcircle.estate.server.framework.entity.UserInfo;
import com.pointcircle.estate.server.framework.repository.UserInfoRepository;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

@RestController
@Slf4j
public class LoginRest {
	
	@Autowired
	private PropertyService propertyService;
	
	@Autowired
	private UserRepository userRepository;
	
	@Autowired
	private UserInfoRepository userInfoRepository;
	
	@Getter
	@Setter
	public static class LoginForm {
		private String username;
		private String password;
	}
	
	@RequestMapping("login")
	public RestResponse login(@RequestBody LoginForm loginForm) {
		try {
			String username = loginForm.getUsername();
			String password = loginForm.getPassword();
			SimpleHash simpleHash = new SimpleHash("sha-1", password);
			simpleHash.setIterations(1);
			String passwordHex = simpleHash.toHex();
			User user = userRepository.findByUsername(username);
			if(user == null || !StringUtils.equals(user.getPasswordHex(), passwordHex)) {
				throw new AuthenticationException(
					propertyService.getProperty("pointcircle.framework.message.auth.username-or-password-wrong")
				);
			}
			UserInfo userInfo = userInfoRepository.findByUser(user);
			String jwtToken = JwtUtils.sign(user.getId(), user.getPasswordHex());
			RestResponseLoginStatus res = new RestResponseLoginStatus();
			res.getUserInfo().setJwtToken(jwtToken);
			res.getUserInfo().setRealname(user.getRealname());
			res.getUserInfo().setUsername(user.getUsername());
			res.getUserInfo().setUserId(user.getId());
			res.getUserInfo().setPhone(userInfo != null ? userInfo.getMobilephone() : null);
			res.getUserInfo().setEmail(userInfo != null ? userInfo.getEmail() : null);
			res.getUserInfo().setAppPermission(userInfo != null ? userInfo.getAppPermission() : null);
			return res;
		} catch(Exception e) {
			log.error(e.getMessage(), e);
			RestResponse res = RestResponseUtils.fail(FrameworkConstant.ERROR_CODE_LOGIN_FAIL, e.getMessage());
			return res;
		}
	}
	
	@GetMapping("loginStatus")
	public RestResponse loginStatus(HttpServletRequest request) {
		try {
			String jwtToken = WebUtils.getCleanParam(request, FrameworkConstant.JWT_TOKEN_KEY);
			if(StringUtils.isEmpty(jwtToken)) {
				jwtToken = request.getHeader(FrameworkConstant.JWT_TOKEN_KEY);
			}
			if(StringUtils.isEmpty(jwtToken)) {
				throw new AuthenticationException(
					propertyService.getProperty("pointcircle.framework.message.auth.token-invalid")
				);
			}
			String userId = JwtUtils.getUserId(jwtToken);
			if(userId == null) {
				throw new AuthenticationException(
					propertyService.getProperty("pointcircle.framework.message.auth.token-invalid")
				);
			}
			User user = userRepository.findOne(userId);
			if(user == null) {
				throw new AuthenticationException(
					propertyService.getProperty("pointcircle.framework.message.auth.user-not-exist")
				);
			}
			UserInfo userInfo = userInfoRepository.findByUser(user);
			RestResponseLoginStatus res = new RestResponseLoginStatus();
			res.getUserInfo().setJwtToken(jwtToken);
			res.getUserInfo().setRealname(user.getRealname());
			res.getUserInfo().setUsername(user.getUsername());
			res.getUserInfo().setUserId(user.getId());
			res.getUserInfo().setPhone(userInfo != null ? userInfo.getMobilephone() : null);
			res.getUserInfo().setEmail(userInfo != null ? userInfo.getEmail() : null);
			res.getUserInfo().setAppPermission(userInfo != null ? userInfo.getAppPermission() : null);
			return res;
		} catch(Exception e) {
			log.error(e.getMessage(), e);
			RestResponse res = RestResponseUtils.fail(FrameworkConstant.ERROR_CODE_LOGIN_STATUS_FAIL, e.getMessage());
			return res;
		}
	}
	
	@Getter
	@Setter
	public static class RestResponseLoginStatus extends RestResponse {
		private UserInfoVo userInfo = new UserInfoVo();
		
		@Getter
		@Setter
		public static class UserInfoVo {
			private String userId;
			private String username;
			private String realname;
			private String appPermission;
			private String phone;
			private String email;
			private String jwtToken;
		}
	}
}
